package com.fourtwoeight.controllers;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.fourtwoeight.controllers.FileWrapper;
import com.fourtwoeight.controllers.WebConstants;
import com.fourtwoeight.imaging.ImageMagickThumbnailProcessor;
import com.fourtwoeight.imaging.NativeJavaThumbnailProcessor;
import com.fourtwoeight.imaging.ThumbnailProcessor;

public class DisplayThumbs implements Controller {

	protected Log logger;
	protected String currentBrowsedDirectory = null;
	protected String currentDirectoryToProcess = null;
	protected String baseImageDirectory = null;

	public static final String[] validExtensions = {"JPG", "JPEG", "jpeg", "jpg", "GIF", "gif", "BMP"};
	private List<FileWrapper> entireDirectoryListing;
	private List<FileWrapper> filesOnlyListing;

	private HttpServletRequest _request;

	public ModelAndView handleRequest(HttpServletRequest request,
										HttpServletResponse response)
    									throws ServletException, IOException {
		_request = request;

		logger = LogFactory.getLog(this.getClass());

		//Get the directory that is being viewed
		currentBrowsedDirectory = (String) request.getParameter(WebConstants.CURRENT_DIRECTORY);
		if(currentBrowsedDirectory == null) {
			currentBrowsedDirectory = "";
		}
		//Get the base image directory
		baseImageDirectory = getBaseDirectory();

		//If no base image dir..bad thing
		if(baseImageDirectory == null) {
			return null;
		}

		// if this is true, this'll be the first time in
		if(currentBrowsedDirectory == null || currentBrowsedDirectory.length() < 1) {
			currentDirectoryToProcess = baseImageDirectory;
		} else {
			currentDirectoryToProcess = baseImageDirectory + currentBrowsedDirectory;
		}


		//logger.debug("Setting current directory to process: " + currentDirectoryToProcess);
		//logger.debug("Current browsed directory: " + currentBrowsedDirectory);

		// make sure it's a directory
		File currentDir = new File(currentDirectoryToProcess);

		if(!currentDir.exists()) {
			logger.error(currentDir + " does not exist");
			return null;
		}

		if(!currentDir.isDirectory()) {
			logger.error(currentDir + " not a directory");
			return null;
		}

		// list files/directories



		listAndSortFiles(currentDir);


		request.setAttribute(WebConstants.CURRENT_DIRECTORY_LIST, entireDirectoryListing);
		request.setAttribute(WebConstants.CURRENT_DIRECTORY_FILE_LIST, filesOnlyListing);
		request.setAttribute(WebConstants.IMAGE_DIRECTORY_URL, getImageDirectoryURL(request));
		request.getSession().setAttribute(WebConstants.CURRENT_DIRECTORY, currentBrowsedDirectory);


		return new ModelAndView("displayThumbnails.jsp");
	}

	protected void listAndSortFiles(File currentDir) {

		entireDirectoryListing = new ArrayList<FileWrapper>();
		filesOnlyListing = new ArrayList<FileWrapper>();

		//logger.debug("Current directory: " + currentDir);

		File[] files = currentDir.listFiles();
		try {
			for (int i = 0; i < files.length; i++) {

				if (files[i].getName().indexOf("_thumb") < 0
						&& files[i].getName().indexOf("_notes") < 0
						&& files[i].getName().indexOf("_slides") < 0) {

					if (files[i].isFile()) {
						try {
							processThumbnail(files[i], "thumb", 94, 94);
							FileWrapper wrappedFile = new FileWrapper(files[i]);
							entireDirectoryListing.add(wrappedFile);
							filesOnlyListing.add(wrappedFile);
						} catch (Exception e) {
							logger.error("Error processing file: " + files[i]);
						}
					} else {
						if (files[i].isDirectory()) {
							FileWrapper wrappedFile = new FileWrapper(files[i]);
							entireDirectoryListing.add(wrappedFile);
						}
					}

				}

			}
		} catch (Exception e) {
			logger.error(e.getMessage() + " stacktrace: ");
			e.printStackTrace();
		}
		Comparator object = new Comparator() {
			public int compare(Object arg0, Object arg1) {
				FileWrapper g0 = (FileWrapper) arg0;
				FileWrapper g1 = (FileWrapper) arg1;

				if(g0.getActualFileToDisplay().isDirectory()
						&& g1.getActualFileToDisplay().isDirectory()) {
					//sort normally for directories
					return g0.getActualFileToDisplay().getName().compareToIgnoreCase(g1.getActualFileToDisplay().getName());
				} else {
					//but put directories first in the list if there's one of each
					if(!g0.getActualFileToDisplay().isDirectory()
							&& g1.getActualFileToDisplay().isDirectory()) {
						return 1;
					} else {
						return g0.getActualFileToDisplay().getName().compareToIgnoreCase(g1.getActualFileToDisplay().getName());
					}
				}

			}
		};
		Collections.sort(entireDirectoryListing, object);
	}

	/*protected void rotateImage(File image, String prefix, int angle) {
		try {

			if(isValidExtension(image.getName())) {
				long start = System.currentTimeMillis();
				//logger.debug("Img name: " + image.getPath());
				//logger.debug("New name: " + newFilename);
				ThumbnailProcessor ih = new ThumbnailProcessor();
				ih.loadImage(image.getPath());
		        ih.rotate(angle);
		        //ih.saveImage(image.getPath());

		        logger.debug(image.getPath() + " rotated in " + (System.currentTimeMillis() - start) + "ms");
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}*/

	protected void processThumbnail(File image, String prefix, int width, int height) {

		//logger.debug("Image parent path: " + image.getParent().toString());

		String thumbsDirectoryString = image.getParent() + File.separatorChar + "_" + prefix;

		File thumbNailsDirectory = new File(thumbsDirectoryString);
		if(!thumbNailsDirectory.exists()) {

			 // Create a directory; all ancestor directories must exist
		    boolean success = thumbNailsDirectory.mkdir();
		    if (!success) {
		        // Directory creation failed
		    }

		    // Create a directory; all non-existent ancestor directories are
		    // automatically created
		    success = thumbNailsDirectory.mkdirs();

		    if (!success) {
		        // Directory creation failed
		    }
		}

		try {
			String fileName = "_" + prefix + File.separatorChar + prefix + "_" + image.getName();
			String fullFilename = image.getParent() + File.separatorChar
					+ fileName;

			File potentialNewImageFile = new File(fullFilename);

			if(isValidExtension(image.getName()) &&
					!potentialNewImageFile.exists() &&
					potentialNewImageFile.lastModified() < image.lastModified()) {

				long start = System.currentTimeMillis();
				//logger.debug("Img name: " + image.getPath());
				//logger.debug("New name: " + newFilename);
				ThumbnailProcessor ih = new ImageMagickThumbnailProcessor(image.getPath());

		        ih.scaleToFit(width, height, fullFilename);

		        logger.debug(fileName + " scaled in " + (System.currentTimeMillis() - start) + "ms");
			}


		} catch (Exception e) {
			e.printStackTrace();
		}


	}

	protected String getBaseDirectory() {
		String bDir = _request.getSession().getServletContext().getInitParameter(WebConstants.BASE_IMAGE_DIRECTORY);
		return bDir;
	}

	protected String getImageDirectoryURL(HttpServletRequest request) {
		String bDir = (String)request.getSession().getAttribute(WebConstants.IMAGE_DIRECTORY_URL);
		if(bDir == null) {
			bDir = request.getSession().getServletContext().getInitParameter(WebConstants.IMAGE_DIRECTORY_URL);
			request.getSession().setAttribute(WebConstants.IMAGE_DIRECTORY_URL, bDir);
		}
		return bDir;
	}

	public static boolean isValidExtension(String filename) {

		for (int i = 0; i < validExtensions.length; i++) {
			String array_element = validExtensions[i];

			if(filename.endsWith(array_element)) {
				return true;
			}
		}

		return false;
	}

	protected String subtractString(String text, String thingToRemove) {
		String result = null;
		if(text == null) {
			//logger.error("Incoming target text is null");
			return "";
		}
		if(thingToRemove == null) {
			//logger.error("Incoming removal text is null");
			return "";
		}
		if (text.length() > thingToRemove.length()) {
			result = text.substring(thingToRemove.length(), text.length());
		} else {
			return "";
		}
		if(result == null) {
			return "/";
		}
		return result;
	}
}
